package com.scs.application.modules.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.sys.dto.SaveAuthorityDTO;
import com.scs.application.modules.sys.entity.Authority;
import com.scs.application.modules.sys.entity.Menu;
import com.scs.application.modules.sys.mapper.AuthorityMapper;
import com.scs.application.modules.sys.service.AuthorityService;
import com.scs.application.modules.sys.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 */
@Service
public class AuthorityServiceImpl extends BaseServiceImpl<AuthorityMapper, Authority> implements AuthorityService {
    @Autowired
    MenuService menuService;

    @Override
    public Boolean saveAuthority(SaveAuthorityDTO para) {
        remove(new QueryWrapper<Authority>().eq("target_id",para.getRoleId())
                .eq("target_type",para.getTargetType()));
        String[] resourceIdArray = para.getResourceIds().split(",");
        for(int i=0;i<resourceIdArray.length;i++) {
            if (resourceIdArray[i].length() == 0) continue;
            Authority authority = new Authority();
            authority.setTargetId(para.getRoleId());
            authority.setTargetType(para.getTargetType());
            authority.setResourceId(resourceIdArray[i]);
            saveOrUpdate(authority);
        }
        return true;
    }
    @Override
    public List<Authority> getRoleAuthority(String roleId) {
        return this.list(new QueryWrapper<Authority>()
                .eq("target_id",roleId)
                .eq("target_type", "R"));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addOrDeleteMenus(@RequestBody Map<String, String> reqData) {
        String roleId = String.valueOf(reqData.get("id"));
        String opType = String.valueOf(reqData.get("opType"));
        String[] menuIdArr = String.valueOf(reqData.get("nodeIds")).split(",");
        if (StringUtils.isBlank(roleId)) throw  new BusinessException("操作失败，缺少参数【roleId】");
        if (StringUtils.isBlank(opType)) throw  new BusinessException("操作失败，缺少参数【opType】");
        if (menuIdArr == null || menuIdArr.length < 1) throw  new BusinessException("操作失败，缺少参数【nodeIds】");


        if ("1".equals(opType)) { //添加菜单
            List<Authority> authorityList = new ArrayList<Authority>();
            Authority authority =null;
            for(int i=0;i<menuIdArr.length;i++) {
                authority = new Authority();
                authority.setTargetId(roleId);
                authority.setTargetType("R");
                authority.setResourceId(menuIdArr[i]);
                authorityList.add(authority);
            }
            this.saveBatch(authorityList);
        } else  if ("-1".equals(opType)){
            baseMapper.delete(new QueryWrapper<Authority>().eq("target_id",roleId)
                    .eq("target_type","R").in("resource_id",menuIdArr));

            //修复权限父节点，有子节点的权限，肯定也要有父节点的权限
            List<Menu> menuList = menuService.list(Wrappers.<Menu>query().inSql("id","SELECT resource_id FROM sys_authority where target_id = '"+roleId+"'"));;
            if (menuList != null && menuList.size() > 0) {
                List<Menu> menuAllList = menuService.list(Wrappers.<Menu>query().orderByAsc("sort"));
                List<Menu> menuAddList = getMenuParent(menuList,menuAllList);
                if (menuAddList != null && menuAddList.size() > 0) {
                    List<Authority> authorityList = new ArrayList<Authority>();
                    Authority authority =null;
                    for(int i=0;i<menuAddList.size();i++) {
                        authority = new Authority();
                        authority.setTargetId(roleId);
                        authority.setTargetType("R");
                        authority.setResourceId(menuAddList.get(i).getId());
                        authorityList.add(authority);
                    }
                    this.saveBatch(authorityList);
                }
            }
        }
    }

    private List<Menu> getMenuParent(List<Menu> menuList,List<Menu> menuAllList){
        List<Menu> menuAddList = new ArrayList<Menu>();
        List<Menu> finalMenuList = menuList;
        menuList.stream().forEach(menu -> {
            if (StringUtils.isNotBlank(menu.getParentId()) && !"0".equals(menu.getParentId())) {
                List<Menu> menuParentList = finalMenuList.stream().filter(menu2 -> menu2.getId().equals(menu.getParentId())).collect(Collectors.toList());
                if (menuParentList ==null || menuParentList.size() < 1){
                    List<Menu> menuParent2List = menuAllList.stream().filter(
                            menu2 -> menu2.getId().equals(menu.getParentId())

                    ).collect(Collectors.toList());
                    if (menuParent2List !=null && menuParent2List.size() > 1){
                        throw  new BusinessException("菜单异常，主键重复，id=%s",menu.getParentId());
                    }
                    if (menuParent2List ==null || menuParent2List.size() < 1){
                        throw  new BusinessException("菜单异常，未找到父级菜单，parentid=%s",menu.getParentId());
                    }

                    //排除掉已隐藏的或者管理员菜单，app可以显示
                    if(
                            (
                                    !"app".equalsIgnoreCase(menuParent2List.get(0).getMenuType())
                                            &&
                                            (menuParent2List.get(0).getIsAdminMenu() ==null || !menuParent2List.get(0).getIsAdminMenu())
                                            && (menuParent2List.get(0).getIsHidden() == null || !menuParent2List.get(0).getIsHidden())
                            )
                                    ||(
                                    "app".equalsIgnoreCase(menuParent2List.get(0).getMenuType())
                                            && (menuParent2List.get(0).getIsHidden() == null || !menuParent2List.get(0).getIsHidden())
                            )
                    )
                    {
                        menuAddList.add(menuParent2List.get(0));
                    }
                }
            }
        });
        if (menuAddList.size() > 0){
            menuAddList.addAll(this.getMenuParent(menuAddList,menuAllList));
            return menuAddList;
        }
        return menuAddList;
    }

    /**
     * @Description：增加或者删除角色菜单
     * @param  roleId           角色id
     * @param  addMenuIds       需要添加的菜单id列表
     * @param  deleteMenuIds    需要删除的菜单id列表
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addOrDelete(String roleId, String addMenuIds,String deleteMenuIds) {
        if (StringUtils.isNotBlank(addMenuIds)) { //添加菜单
            List<Authority> authorityList = new ArrayList<Authority>();
            Authority authority =null;
            for(String menuId : addMenuIds.split(",")) {
                authority = new Authority();
                authority.setTargetId(roleId);
                authority.setTargetType("R");
                authority.setResourceId(menuId);
                authorityList.add(authority);
            }
            this.saveBatch(authorityList);
        }

        if (StringUtils.isNotBlank(deleteMenuIds)){
            String[] deleteMenuIdArr = deleteMenuIds.split(",");
            baseMapper.delete(new QueryWrapper<Authority>().eq("target_id",roleId)
                    .eq("target_type","R").in("resource_id",deleteMenuIdArr));
        }

        //修复权限父节点，有子节点的权限，肯定也要有父节点的权限
        List<Menu> menuList = menuService.list(Wrappers.<Menu>query().inSql("id","SELECT resource_id FROM sys_authority where target_id = '"+roleId+"'"));;
        if (menuList != null && menuList.size() > 0) {
            List<Menu> menuAllList = menuService.list(Wrappers.<Menu>query().orderByAsc("sort"));
            List<Menu> menuAddList = getMenuParent(menuList,menuAllList);
            if (menuAddList != null && menuAddList.size() > 0) {
                List<Authority> authorityList = new ArrayList<Authority>();
                Authority authority =null;
                for(int i=0;i<menuAddList.size();i++) {
                    authority = new Authority();
                    authority.setTargetId(roleId);
                    authority.setTargetType("R");
                    authority.setResourceId(menuAddList.get(i).getId());
                    authorityList.add(authority);
                }
                this.saveBatch(authorityList);
            }
        }
    }
}
